home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / jikes-1.02 / src / control.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-05  |  53.0 KB  |  1,357 lines

  1. // $Id: control.cpp,v 1.16 1999/09/01 14:58:24 shields Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. #include "config.h"
  11. #include <sys/stat.h>
  12. #include "control.h"
  13. #include "scanner.h"
  14. #include "parser.h"
  15. #include "semantic.h"
  16. #include "error.h"
  17. #include "bytecode.h"
  18. #include "case.h"
  19.  
  20.  
  21. Control::Control(ArgumentExpander &arguments, Option &option_) : return_code(0),
  22.                                                                  option(option_),
  23.                                                                  dot_classpath_index(0),
  24.                                                                  system_table(NULL),
  25.                                                                  system_semantic(NULL),
  26.                                                                  semantic(1024),
  27.                                                                  needs_body_work(1024),
  28.                                                                  type_trash_bin(1024),
  29.                                                                  input_java_file_set(1021),
  30.                                                                  input_class_file_set(1021),
  31.                                                                  expired_file_set(),
  32.                                                                  recompilation_file_set(1021),
  33.                                                                  Object_type(NULL),
  34.                                                                  Cloneable_type(NULL),
  35.                                                                  Serializable_type(NULL),
  36.                                                                  String_type(NULL),
  37.                                                                  Void_type(NULL),
  38.                                                                  Boolean_type(NULL),
  39.                                                                  Byte_type(NULL),
  40.                                                                  Short_type(NULL),
  41.                                                                  Character_type(NULL),
  42.                                                                  Integer_type(NULL),
  43.                                                                  Long_type(NULL),
  44.                                                                  Float_type(NULL),
  45.                                                                  Double_type(NULL),
  46.                                                                  Class_type(NULL),
  47.                                                                  Throwable_type(NULL),
  48.                                                                  RuntimeException_type(NULL),
  49.                                                                  ClassNotFoundException_type(NULL),
  50.                                                                  Error_type(NULL),
  51.                                                                  NoClassDefFoundError_type(NULL),
  52.                                                                  StringBuffer_type(NULL),
  53.  
  54.                                                                  Class_forName_method(NULL),
  55.  
  56.                                                                  Throwable_getMessage_method(NULL),
  57.  
  58.                                                                  NoClassDefFoundError_InitWithString_method(NULL),
  59.  
  60.                                                                  StringBuffer_Init_method(NULL),
  61.                                                                  StringBuffer_InitWithString_method(NULL),
  62.                                                                  StringBuffer_toString_method(NULL),
  63.                                                                  StringBuffer_append_char_array_method(NULL),
  64.                                                                  StringBuffer_append_char_method(NULL),
  65.                                                                  StringBuffer_append_boolean_method(NULL),
  66.                                                                  StringBuffer_append_int_method(NULL),
  67.                                                                  StringBuffer_append_long_method(NULL),
  68.                                                                  StringBuffer_append_float_method(NULL),
  69.                                                                  StringBuffer_append_double_method(NULL),
  70.                                                                  StringBuffer_append_string_method(NULL),
  71.                                                                  StringBuffer_append_object_method(NULL),
  72.  
  73.                                                                  int_pool(&bad_value),
  74.                                                                  long_pool(&bad_value),
  75.                                                                  float_pool(&bad_value),
  76.                                                                  double_pool(&bad_value),
  77.                                                                  Utf8_pool(&bad_value)
  78.  
  79. #ifdef TEST
  80.                                                                , line_count(0),
  81.                                                                  class_files_read(0),
  82.                                                                  class_files_written(0),
  83.                                                                  input_files_processed(0)
  84. #endif
  85. {
  86.     ProcessGlobals();
  87.  
  88.     ProcessUnnamedPackage();
  89.  
  90.     ProcessPath();
  91.  
  92.     ProcessSystemInformation();
  93.  
  94.     //
  95.     // Instantiate a scanner and a parser and initialize the static members for the semantic processors.
  96.     //
  97.     scanner = new Scanner(*this);
  98.     parser = new Parser();
  99.     SemanticError::StaticInitializer();
  100.  
  101.     //
  102.     // Process all file names specified in command line
  103.     //
  104.     ProcessNewInputFiles(input_java_file_set, arguments, option.first_file_index);
  105.  
  106.     //
  107.     // For each input file, copy it into the input_files array and process its package declaration.
  108.     //
  109.     StoragePool *ast_pool = new StoragePool(64); // how much space do we need? estimate 64 tokens.
  110.     FileSymbol **input_files = new FileSymbol*[input_java_file_set.Size() + 1];
  111.     int num_files = 0;
  112.     for (FileSymbol *file_symbol = (FileSymbol *) input_java_file_set.FirstElement();
  113.                      file_symbol;
  114.                      file_symbol = (FileSymbol *) input_java_file_set.NextElement())
  115.     {
  116.         input_files[num_files++] = file_symbol;
  117.         scanner -> Scan(file_symbol);
  118.         if (file_symbol -> lex_stream) // did we have a successful scan!
  119.         {
  120.             AstPackageDeclaration *package_declaration = parser -> PackageHeaderParse(file_symbol -> lex_stream, ast_pool);
  121.             ProcessPackageDeclaration(file_symbol, package_declaration);
  122.             ast_pool -> Reset();
  123.         }
  124.     }
  125.  
  126.     //
  127.     //
  128.     //
  129.     FileSymbol *main_file_clone;
  130.     if (num_files > 0)
  131.         main_file_clone = input_files[0] -> Clone();
  132.     else
  133.     {
  134.         //
  135.         // Some name, any name !!! We use dot_name_symbol as a bad file name because
  136.         // no file can be named ".".
  137.         //
  138.         FileSymbol *file_symbol = classpath[dot_classpath_index] -> RootDirectory() -> InsertFileSymbol(dot_name_symbol);
  139.         file_symbol -> directory_symbol = classpath[dot_classpath_index] -> RootDirectory();
  140.         file_symbol -> SetJava();
  141.  
  142.         main_file_clone = file_symbol -> Clone();
  143.     }
  144.  
  145.     main_file_clone -> semantic = new Semantic(*this, main_file_clone);
  146.     system_semantic = main_file_clone -> semantic;
  147.     scanner -> SetUp(main_file_clone);
  148.  
  149. #ifdef WIN32_FILE_SYSTEM
  150.     //
  151.     //
  152.     //
  153.     if (option.BadMainDisk())
  154.     {
  155.         system_semantic -> ReportSemError(SemanticError::NO_CURRENT_DIRECTORY,
  156.                                           0,
  157.                                           0);
  158.     }
  159. #endif
  160.  
  161.     //
  162.     //
  163.     //
  164.     for (int o = 0; o < option.bad_options.Length(); o++)
  165.     {
  166.         system_semantic -> ReportSemError((SemanticError::SemanticErrorKind) option.bad_options[o] -> kind,
  167.                                           0,
  168.                                           0,
  169.                                           option.bad_options[o] -> name);
  170.     }
  171.  
  172.     //
  173.     //
  174.     //
  175.     for (int l = 0; l < bad_zip_filenames.Length(); l++)
  176.     {
  177.         wchar_t *tail = &bad_zip_filenames[l][wcslen(bad_zip_filenames[l]) - 3];
  178.  
  179.         system_semantic -> ReportSemError(Case::StringSegmentEqual(tail, StringConstant::US__zip, 3) ||
  180.                                           Case::StringSegmentEqual(tail, StringConstant::US__jar, 3)
  181.                                                ? SemanticError::CANNOT_OPEN_ZIP_FILE
  182.                                                : SemanticError::CANNOT_OPEN_PATH_DIRECTORY,
  183.                                           0,
  184.                                           0,
  185.                                           bad_zip_filenames[l]);
  186.     }
  187.  
  188.     //
  189.     //
  190.     //
  191.     if (system_package -> directory.Length() == 0)
  192.     {
  193.         system_semantic -> ReportSemError(SemanticError::PACKAGE_NOT_FOUND,
  194.                                           0,
  195.                                           0,
  196.                                           StringConstant::US_java_SL_lang);
  197.     }
  198.  
  199.     //
  200.     // When the -d option is specified, create the relevant
  201.     // directories if they don't already exist.
  202.     //
  203.     if (option.directory)
  204.     {
  205.         if (! ::SystemIsDirectory(option.directory))
  206.         {
  207.             for (char *ptr = option.directory; *ptr; ptr++)
  208.             {
  209.                 char delimiter = *ptr;
  210.                 if (delimiter == U_SLASH)
  211.                 {
  212.                     *ptr = U_NULL;
  213.  
  214.                     if (! ::SystemIsDirectory(option.directory))
  215.                         ::SystemMkdir(option.directory);
  216.  
  217.                     *ptr = delimiter;
  218.                 }
  219.             }
  220.  
  221.             ::SystemMkdir(option.directory);
  222.  
  223.             if (! ::SystemIsDirectory(option.directory))
  224.             {
  225.                 int length = strlen(option.directory);
  226.                 wchar_t *name = new wchar_t[length + 1];
  227.                 for (int i = 0; i < length; i++)
  228.                     name[i] = option.directory[i];
  229.                 name[length] = U_NULL;
  230.                 system_semantic -> ReportSemError(SemanticError::CANNOT_OPEN_DIRECTORY,
  231.                                                   0,
  232.                                                   0,
  233.                                                   name);
  234.                 delete [] name;
  235.             }
  236.         }
  237.     }
  238.  
  239.     //
  240.     //
  241.     //
  242.     for (int m = 0; m < bad_input_filenames.Length(); m++)
  243.     {
  244.         system_semantic -> ReportSemError(SemanticError::BAD_INPUT_FILE,
  245.                                           0,
  246.                                           0,
  247.                                           bad_input_filenames[m]);
  248.     }
  249.  
  250.     //
  251.     //
  252.     //
  253.     for (int n = 0; n < unreadable_input_filenames.Length(); n++)
  254.     {
  255.         system_semantic -> ReportSemError(SemanticError::UNREADABLE_INPUT_FILE,
  256.                                           0,
  257.                                           0,
  258.                                           unreadable_input_filenames[n]);
  259.     }
  260.  
  261.     //
  262.     //
  263.     //
  264.     if (system_semantic -> NumErrors() > 0)
  265.         system_semantic -> PrintMessages();
  266.     else
  267.     {
  268.         system_semantic -> PrintMessages(); // there might be some warnings we want to print...
  269.  
  270.         //
  271.         //
  272.         //
  273.         input_java_file_set.SetEmpty();
  274.         for (int i = 0; i < num_files; i++)
  275.         {
  276.             FileSymbol *file_symbol = input_files[i];
  277.             if (! input_java_file_set.IsElement(file_symbol))
  278.                 ProcessFile(file_symbol);
  279.         }
  280.  
  281.         //
  282.         // Clean up all the files that have just been compiled in this new batch.
  283.         //
  284.         for (FileSymbol *file_symbol = (FileSymbol *) input_java_file_set.FirstElement();
  285.                          file_symbol;
  286.                          file_symbol = (FileSymbol *) input_java_file_set.NextElement())
  287.         {
  288.             CleanUp(file_symbol);
  289.         }
  290.  
  291.         //
  292.         // If more messages were added to system_semantic, print them...
  293.         //
  294.         system_semantic -> PrintMessages();
  295.         if (system_semantic -> return_code > 0 || bad_input_filenames.Length() > 0 || unreadable_input_filenames.Length() > 0)
  296.             return_code = 1;
  297.  
  298.         //
  299.         // If the incremental flag is on, check to see if the user wants us to recompile.
  300.         //
  301.         if (option.incremental)
  302.         {
  303.             option.depend = false; // The depend flag should only be in effect in the first pass
  304.  
  305.             for (bool recompile = IncrementalRecompilation(); recompile; recompile = IncrementalRecompilation())
  306.             {
  307.                 return_code = 0; // reset the return code as we may compile clean in this pass
  308.                 system_semantic -> return_code = 0;
  309.  
  310.                 //
  311.                 //
  312.                 //
  313.                 for (int m = 0; m < bad_input_filenames.Length(); m++)
  314.                 {
  315.                     system_semantic -> ReportSemError(SemanticError::BAD_INPUT_FILE,
  316.                                                       0,
  317.                                                       0,
  318.                                                       bad_input_filenames[m]);
  319.                 }
  320.  
  321.                 //
  322.                 //
  323.                 //
  324.                 for (int n = 0; n < unreadable_input_filenames.Length(); n++)
  325.                 {
  326.                     system_semantic -> ReportSemError(SemanticError::UNREADABLE_INPUT_FILE,
  327.                                                       0,
  328.                                                       0,
  329.                                                       unreadable_input_filenames[n]);
  330.                 }
  331.  
  332.                 FileSymbol *file_symbol;
  333.  
  334.                 num_files = 0;
  335.                 delete [] input_files; // delete previous copy
  336.                 input_files = new FileSymbol*[recompilation_file_set.Size()];
  337.                 for (file_symbol = (FileSymbol *) recompilation_file_set.FirstElement();
  338.                      file_symbol;
  339.                      file_symbol = (FileSymbol *) recompilation_file_set.NextElement())
  340.                 {
  341.                     input_java_file_set.RemoveElement(file_symbol);
  342.                     input_files[num_files++] = file_symbol;
  343.  
  344.                     LexStream *lex_stream = file_symbol -> lex_stream;
  345.                     if (lex_stream)
  346.                     {
  347.                         AstPackageDeclaration *package_declaration = parser -> PackageHeaderParse(lex_stream, ast_pool);
  348.                         ProcessPackageDeclaration(file_symbol, package_declaration);
  349.                         ast_pool -> Reset();
  350.                     }
  351.                 }
  352.  
  353.                 //
  354.                 // If a file has been erased, remove it from the input file set.
  355.                 //
  356.                 for (file_symbol = (FileSymbol *) expired_file_set.FirstElement();
  357.                      file_symbol;
  358.                      file_symbol = (FileSymbol *) expired_file_set.NextElement())
  359.                 {
  360.                     input_java_file_set.RemoveElement(file_symbol);
  361.                 }
  362.  
  363.                 //
  364.                 // Reset the global objects before recompiling this new batch.
  365.                 //
  366.                 expired_file_set.SetEmpty();
  367.                 recompilation_file_set.SetEmpty();
  368.                 type_trash_bin.Reset();
  369.  
  370.                 //
  371.                 // For each file that should be recompiled, process it if it has not
  372.                 // already been dragged in by dependence.
  373.                 //
  374.                 for (int k = 0; k < num_files; k++)
  375.                 {
  376.                     FileSymbol *file_symbol = input_files[k];
  377.                     if (! input_java_file_set.IsElement(file_symbol))
  378.                         ProcessFile(file_symbol);
  379.                 }
  380.  
  381.                 //
  382.                 // Clean up all the files that have just been compiled in this new batch.
  383.                 //
  384.                 for (file_symbol = (FileSymbol *) input_java_file_set.FirstElement();
  385.                      file_symbol;
  386.                      file_symbol = (FileSymbol *) input_java_file_set.NextElement())
  387.                 {
  388.                     CleanUp(file_symbol);
  389.                 }
  390.  
  391.                 //
  392.                 // If any system error or warning was detected, print it...
  393.                 //
  394.                 system_semantic -> PrintMessages();
  395.                 if (system_semantic -> return_code > 0 || bad_input_filenames.Length() > 0 || unreadable_input_filenames.Length() > 0)
  396.                     return_code = 1;
  397.             }
  398.         }
  399.  
  400.         //
  401.         // Are we supposed to generate Makefiles?
  402.         //
  403.         if (option.makefile)
  404.         {
  405.             if (option.makefile_name)
  406.             {
  407.                 FILE *outfile = ::SystemFopen(option.makefile_name, "w");
  408.                 if (outfile == NULL)
  409.                     Coutput << "*** Cannot open file " << option.makefile_name << "\n";
  410.                 else
  411.                 {
  412.                     SymbolSet types_in_new_files;
  413.  
  414.                     for (FileSymbol *file_symbol = (FileSymbol *) input_java_file_set.FirstElement();
  415.                                      file_symbol;
  416.                                      file_symbol = (FileSymbol *) input_java_file_set.NextElement())
  417.                     {
  418.                         char *java_name = file_symbol -> FileName();
  419.  
  420.                         for (int j = 0; j < file_symbol -> types.Length(); j++)
  421.                         {
  422.                             TypeSymbol *type = file_symbol -> types[j];
  423. #ifdef EBCDIC
  424.                             for (char *p = java_name; *p; p++)
  425.                                  fprintf(outfile, "%c", Code::ToEBCDIC(*p));
  426.                             fprintf(outfile, " : ");
  427.                             for (char *q = type -> SignatureString(); *q; q++)
  428.                                  fprintf(outfile, "%c", Code::ToEBCDIC(*q));
  429.                             fprintf(outfile, "\n");
  430. #else
  431.                             fprintf(outfile, "%s : %s\n", java_name, type -> SignatureString());
  432. #endif
  433.  
  434.                             //
  435.                             //
  436.                             //
  437.                             for (TypeSymbol *static_parent = (TypeSymbol *) type -> static_parents -> FirstElement();
  438.                                              static_parent;
  439.                                              static_parent = (TypeSymbol *) type -> static_parents -> NextElement())
  440.                             {
  441.                                 if (! type -> parents -> IsElement(static_parent)) // Only a static reference to static_parent?
  442.                                 {
  443. #ifdef EBCDIC
  444.                                     fprintf(outfile, "   !");
  445.                                     for (char *q = static_parent -> SignatureString(); *q; q++)
  446.                                          fprintf(outfile, "%c", Code::ToEBCDIC(*q));
  447.                                     fprintf(outfile, "\n");
  448. #else
  449.                                     fprintf(outfile, "   !%s\n", static_parent -> SignatureString());
  450. #endif
  451.  
  452.                                     //
  453.                                     // If the type is contained in a type that is not one of the input files, save it
  454.                                     //
  455.                                     if (static_parent -> file_symbol -> IsClass())
  456.                                         types_in_new_files.AddElement(static_parent);
  457.                                 }
  458.                             }
  459.  
  460.                             //
  461.                             //
  462.                             //
  463.                             for (TypeSymbol *parent = (TypeSymbol *) type -> parents -> FirstElement();
  464.                                              parent;
  465.                                              parent = (TypeSymbol *) type -> parents -> NextElement())
  466.                             {
  467. #ifdef EBCDIC
  468.                                 fprintf(outfile, "    ");
  469.                                 for (char *q = parent -> SignatureString(); *q; q++)
  470.                                      fprintf(outfile, "%c", Code::ToEBCDIC(*q));
  471.                                 fprintf(outfile, "\n");
  472. #else
  473.                                 fprintf(outfile, "    %s\n", parent -> SignatureString());
  474. #endif
  475.  
  476.                                 //
  477.                                 // If the type is contained in a type that is not one of the input files, save it
  478.                                 //
  479.                                 if (parent -> file_symbol -> IsClass())
  480.                                     types_in_new_files.AddElement(parent);
  481.                             }
  482.                         }
  483.                     }
  484.  
  485.                     //
  486.                     // Print the list of class files that are referenced.
  487.                     //
  488.                     for (TypeSymbol *type = (TypeSymbol *) types_in_new_files.FirstElement();
  489.                                      type;
  490.                                      type = (TypeSymbol *) types_in_new_files.NextElement())
  491.                     {
  492.                         char *class_name = type -> file_symbol -> FileName();
  493. #ifdef EBCDIC
  494.                         for (char *p = class_name; *p; p++)
  495.                              fprintf(outfile, "%c", Code::ToEBCDIC(*p));
  496.                         fprintf(outfile, " : ");
  497.                         for (char *q = type -> SignatureString(); *q; q++)
  498.                              fprintf(outfile, "%c", Code::ToEBCDIC(*q));
  499.                         fprintf(outfile, "\n");
  500. #else
  501.                         fprintf(outfile, "%s : %s\n", class_name, type -> SignatureString());
  502. #endif
  503.                     }
  504.  
  505.                     fclose(outfile);
  506.                 }
  507.             }
  508.             else
  509.             {
  510.                 SymbolSet *candidates = new SymbolSet(input_java_file_set.Size() + input_class_file_set.Size());
  511.                 *candidates = input_java_file_set;
  512.                 candidates -> Union(input_class_file_set);
  513.  
  514.                 TypeDependenceChecker *dependence_checker = new TypeDependenceChecker((Control *) this, *candidates, type_trash_bin);
  515.                 dependence_checker -> PartialOrder();
  516.                 dependence_checker -> OutputDependences();
  517.                 delete dependence_checker;
  518.  
  519.                 delete candidates;
  520.             }
  521.         }
  522.     }
  523.  
  524.     delete ast_pool;
  525.  
  526.     delete main_file_clone; // delete the clone of the main source file...
  527.  
  528. #ifdef NO_LEAKS
  529.     delete [] input_files;
  530. #endif
  531.  
  532.     return;
  533. }
  534.  
  535.  
  536. Control::~Control()
  537. {
  538. #ifdef NO_LEAKS
  539.     for (int i = 0; i < bad_zip_filenames.Length(); i++)
  540.         delete [] bad_zip_filenames[i];
  541.  
  542.     for (int j = 0; j < bad_input_filenames.Length(); j++)
  543.         delete [] bad_input_filenames[j];
  544.  
  545.     for (int k = 0; k < unreadable_input_filenames.Length(); k++)
  546.         delete [] unreadable_input_filenames[k];
  547.  
  548.     for (int l = 0; l < system_directories.Length(); l++)
  549.         delete system_directories[l];
  550.  
  551.     delete scanner;
  552.     delete parser;
  553.     delete system_semantic;
  554. #endif
  555.  
  556. #ifdef TEST
  557.     if (option.debug_dump_lex || option.debug_dump_ast)
  558.     {
  559.         Coutput << line_count << " source lines read\n\n"
  560.                 << class_files_read << " \".class\" files read\n"
  561.                 << class_files_written << " \".class\" files written\n"
  562.                 << input_files_processed << " \".java\" files processed\n";
  563.     }
  564. #endif
  565. }
  566.  
  567.  
  568. PackageSymbol *Control::ProcessPackage(wchar_t *name)
  569. {
  570.     int name_length = wcslen(name);
  571.     wchar_t *package_name = new wchar_t[name_length];
  572.     int length;
  573.     for (length = 0; length < name_length && name[length] != U_SLASH; length++)
  574.          package_name[length] = name[length];
  575.     NameSymbol *name_symbol = FindOrInsertName(package_name, length);
  576.  
  577.     PackageSymbol *package_symbol = external_table.FindPackageSymbol(name_symbol);
  578.     if (! package_symbol)
  579.     {
  580.         package_symbol = external_table.InsertPackageSymbol(name_symbol, NULL);
  581.         FindPathsToDirectory(package_symbol);
  582.     }
  583.  
  584.     while(length < name_length)
  585.     {
  586.         int start = ++length;
  587.         for (int i = 0; length < name_length && name[length] != U_SLASH; i++, length++)
  588.              package_name[i] = name[length];
  589.         name_symbol = FindOrInsertName(package_name, length - start);
  590.         PackageSymbol *subpackage_symbol = package_symbol -> FindPackageSymbol(name_symbol);
  591.         if (! subpackage_symbol)
  592.         {
  593.             subpackage_symbol = package_symbol -> InsertPackageSymbol(name_symbol);
  594.             FindPathsToDirectory(subpackage_symbol);
  595.         }
  596.         package_symbol = subpackage_symbol;
  597.     }
  598.  
  599.     delete [] package_name;
  600.  
  601.     return package_symbol;
  602. }
  603.  
  604.  
  605. //
  606. // When searching for a subdirectory in a zipped file, it must already be present in the
  607. // hierarchy.
  608. //
  609. DirectorySymbol *Control::FindSubdirectory(PathSymbol *path_symbol, wchar_t *name, int name_length)
  610. {
  611.     wchar_t *directory_name = new wchar_t[name_length + 1];
  612.  
  613.     DirectorySymbol *directory_symbol = path_symbol -> RootDirectory();
  614.     for (int start = 0, end; directory_symbol && start < name_length; start = end + 1)
  615.     {
  616.         end = start;
  617.         for (int i = 0; end < name_length && name[end] != U_SLASH; i++, end++)
  618.              directory_name[i] = name[end];
  619.         NameSymbol *name_symbol = FindOrInsertName(directory_name, end - start);
  620.         directory_symbol = directory_symbol -> FindDirectorySymbol(name_symbol);
  621.     }
  622.  
  623.     delete [] directory_name;
  624.  
  625.     return directory_symbol;
  626. }
  627.  
  628.  
  629. //
  630. // When searching for a directory in the system, if it is not already present in the hierarchy
  631. // insert it and attempt to read it from the system...
  632. //
  633. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  634.     DirectorySymbol *Control::ProcessSubdirectories(wchar_t *source_name, int source_name_length)
  635.     {
  636.         int name_length = (source_name_length < 0 ? 0 : source_name_length);
  637.         char *input_name = new char[name_length + 1];
  638.         for (int i = 0; i < name_length; i++)
  639.             input_name[i] = source_name[i];
  640.         input_name[name_length] = U_NULL;
  641.  
  642.         DirectorySymbol *directory_symbol = NULL;
  643.         struct stat status;
  644.         if ((::SystemStat(input_name, &status) == 0) && (status.st_mode & STAT_S_IFDIR))
  645.             directory_symbol = system_table -> FindDirectorySymbol(status.st_dev, status.st_ino);
  646.  
  647.         if (! directory_symbol)
  648.         {
  649.             if (input_name[0] == U_SLASH) // file name starts with '/'
  650.             {
  651.                 directory_symbol = new DirectorySymbol(FindOrInsertName(source_name, name_length), classpath[dot_classpath_index]);
  652.                 directory_symbol -> ReadDirectory();
  653.                 system_directories.Next() = directory_symbol;
  654.                 system_table -> InsertDirectorySymbol(status.st_dev, status.st_ino, directory_symbol);
  655.             }
  656.             else
  657.             {
  658.                 wchar_t *name = new wchar_t[name_length + 1];
  659.                 for (int i = 0; i < name_length; i++)
  660.                     name[i] = source_name[i];
  661.                 name[name_length] = U_NULL;
  662.  
  663.                 directory_symbol = classpath[dot_classpath_index] -> RootDirectory(); // start at the dot directory.
  664.  
  665.                 //
  666.                 //
  667.                 //
  668.                 wchar_t *directory_name = new wchar_t[name_length];
  669.                 int end = 0;
  670.                 for (int start = end; start < name_length; start = end)
  671.                 {
  672.                     int length;
  673.                     for (length = 0; end < name_length && name[end] != U_SLASH; length++, end++)
  674.                         directory_name[length] = name[end];
  675.  
  676.                     if (length != 1 || directory_name[0] != U_DOT) // Not the current directory
  677.                     {
  678.                         if (length == 2 && directory_name[0] == U_DOT && directory_name[1] == U_DOT) // keep the current directory
  679.                         {
  680.                             if (directory_symbol -> Identity() == dot_name_symbol ||
  681.                                 directory_symbol -> Identity() == dot_dot_name_symbol)
  682.                             {
  683.                                 DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(dot_dot_name_symbol);
  684.                                 if (! subdirectory_symbol)
  685.                                     subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(dot_dot_name_symbol);
  686.                                 directory_symbol = subdirectory_symbol;
  687.                             }
  688.                             else directory_symbol = directory_symbol -> owner -> DirectoryCast();
  689.                         }
  690.                         else
  691.                         {
  692.                             NameSymbol *name_symbol = FindOrInsertName(directory_name, length);
  693.                             DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(name_symbol);
  694.                             if (! subdirectory_symbol)
  695.                                 subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(name_symbol);
  696.                             directory_symbol = subdirectory_symbol;
  697.                         }
  698.                     }
  699.  
  700.                     for (end++; end < name_length && name[end] == U_SLASH; end++) // skip all extra '/'
  701.                         ;
  702.                 }
  703.  
  704.                 //
  705.                 // Insert the new directory into the system table to avoid duplicates, in case
  706.                 // the same directory is specified with a different name.
  707.                 //
  708.                 if (directory_symbol != classpath[dot_classpath_index] -> RootDirectory()) // Not the dot directory.
  709.                 {
  710.                     system_table -> InsertDirectorySymbol(status.st_dev, status.st_ino, directory_symbol);
  711.                     directory_symbol -> ReadDirectory();
  712.                 }
  713.  
  714.                 delete [] directory_name;
  715.                 delete [] name;
  716.             }
  717.         }
  718.  
  719.         delete [] input_name;
  720.  
  721.         return directory_symbol;
  722.     }
  723. #elif defined(WIN32_FILE_SYSTEM)
  724.     DirectorySymbol *Control::ProcessSubdirectories(wchar_t *source_name, int source_name_length)
  725.     {
  726.         DirectorySymbol *directory_symbol = classpath[dot_classpath_index] -> RootDirectory();
  727.  
  728.         int name_length = (source_name_length < 0 ? 0 : source_name_length);
  729.         wchar_t *name = new wchar_t[name_length + 1];
  730.         char *input_name = new char[name_length + 1];
  731.         for (int i = 0; i < name_length; i++)
  732.             input_name[i] = name[i] = source_name[i];
  733.         input_name[name_length] = name[name_length] = U_NULL;
  734.  
  735.         if (name_length >= 2 && Case::IsAsciiAlpha(input_name[0]) && input_name[1] == U_COLON) // a disk was specified
  736.         {
  737.             char disk = input_name[0];
  738.             option.SaveCurrentDirectoryOnDisk(disk);
  739.             if (SetCurrentDirectory(input_name))
  740.             {
  741.                 DWORD directory_length = GetCurrentDirectory(0, input_name); // first, get the right size
  742.                 char *full_directory_name = new char[directory_length + 1];  // allocate the directory
  743.                 DWORD length = GetCurrentDirectory(directory_length, full_directory_name);
  744.                 if (length <= directory_length)
  745.                 {
  746.                     for (char *ptr = full_directory_name; *ptr; ptr++)
  747.                         *ptr = (*ptr != U_BACKSLASH ? *ptr : (char) U_SLASH); // turn '\' to '/'.
  748.  
  749.                     char *current_directory = option.GetMainCurrentDirectory();
  750.                     int prefix_length = strlen(current_directory);
  751.                     int start = (prefix_length <= length &&
  752.                                  Case::StringSegmentEqual(current_directory, full_directory_name, prefix_length) &&
  753.                                  (full_directory_name[prefix_length] == U_SLASH || full_directory_name[prefix_length] == U_NULL)
  754.                                                 ? prefix_length + 1
  755.                                                 : 0);
  756.  
  757.                     if (start > length)
  758.                          name_length = 0;
  759.                     else if (start <= length) // note that we can assert that (start != length)
  760.                     {
  761.                         delete [] name;
  762.                         name_length = length - start;
  763.                         name = new wchar_t[name_length + 1];
  764.                         for (int k = 0, i = start; i < length; i++, k++)
  765.                             name[k] = full_directory_name[i];
  766.                         name[name_length] = U_NULL;
  767.                     }
  768.                 }
  769.  
  770.                 delete [] full_directory_name;
  771.             }
  772.  
  773.             option.ResetCurrentDirectoryOnDisk(disk);  // reset the current directory on this disk
  774.             option.SetMainCurrentDirectory(); // reset the real current directory...
  775.         }
  776.  
  777.         //
  778.         //
  779.         //
  780.         int end;
  781.         if (name_length > 2 && Case::IsAsciiAlpha(name[0]) && name[1] == U_COLON && name[2] == U_SLASH)
  782.             end = 3;
  783.         else
  784.         {
  785.             for (end = 0; end < name_length && name[end] == U_SLASH; end++) // keep all extra leading '/'
  786.                 ;
  787.         }
  788.  
  789.         //
  790.         //
  791.         //
  792.         wchar_t *directory_name = new wchar_t[name_length];
  793.         int length;
  794.         if (end > 0)
  795.         {
  796.             for (length = 0; length < end; length++)
  797.                 directory_name[length] = name[length];
  798.             NameSymbol *name_symbol = FindOrInsertName(directory_name, length);
  799.             DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(name_symbol);
  800.             if (! subdirectory_symbol)
  801.                 subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(name_symbol);
  802.             directory_symbol = subdirectory_symbol;
  803.         }
  804.  
  805.         //
  806.         //
  807.         //
  808.         for (int start = end; start < name_length; start = end)
  809.         {
  810.             for (length = 0; end < name_length && name[end] != U_SLASH; length++, end++)
  811.                 directory_name[length] = name[end];
  812.  
  813.             if (length != 1 || directory_name[0] != U_DOT) // Not the current directory
  814.             {
  815.                 if (length == 2 && directory_name[0] == U_DOT && directory_name[1] == U_DOT) // keep the current directory
  816.                 {
  817.                     if (directory_symbol -> Identity() == dot_name_symbol || directory_symbol -> Identity() == dot_dot_name_symbol)
  818.                     {
  819.                         DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(dot_dot_name_symbol);
  820.                         if (! subdirectory_symbol)
  821.                             subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(dot_dot_name_symbol);
  822.                         directory_symbol = subdirectory_symbol;
  823.                     }
  824.                     else directory_symbol = directory_symbol -> owner -> DirectoryCast();
  825.                 }
  826.                 else
  827.                 {
  828.                     NameSymbol *name_symbol = FindOrInsertName(directory_name, length);
  829.                     DirectorySymbol *subdirectory_symbol = directory_symbol -> FindDirectorySymbol(name_symbol);
  830.                     if (! subdirectory_symbol)
  831.                         subdirectory_symbol = directory_symbol -> InsertDirectorySymbol(name_symbol);
  832.                     directory_symbol = subdirectory_symbol;
  833.                 }
  834.             }
  835.  
  836.             for (end++; end < name_length && name[end] == U_SLASH; end++) // skip all extra '/'
  837.                 ;
  838.         }
  839.  
  840.         directory_symbol -> ReadDirectory();
  841.  
  842.         delete [] directory_name;
  843.         delete [] name;
  844.         delete [] input_name;
  845.  
  846.         return directory_symbol;
  847.     }
  848. #endif
  849.  
  850.  
  851. void Control::ProcessNewInputFiles(SymbolSet &file_set, ArgumentExpander &arguments, int first_index)
  852. {
  853.     for (int i = 0; i < bad_input_filenames.Length(); i++)
  854.         delete [] bad_input_filenames[i];
  855.     bad_input_filenames.Reset();
  856.  
  857.     for (int k = 0; k < unreadable_input_filenames.Length(); k++)
  858.         delete [] unreadable_input_filenames[k];
  859.     unreadable_input_filenames.Reset();
  860.  
  861.     //
  862.     // Process all file names specified in command line
  863.     //
  864.     for (int j = first_index; j < arguments.argc; j++)
  865.     {
  866.         char *file_name = arguments.argv[j];
  867.         int file_name_length = strlen(file_name);
  868.  
  869.         wchar_t *name = new wchar_t[file_name_length + 1];
  870.         for (int i = 0; i < file_name_length; i++)
  871.             name[i] = (file_name[i] != U_BACKSLASH ? file_name[i] : (wchar_t) U_SLASH); // change backslash to forward slash.
  872.         name[file_name_length] = U_NULL;
  873.  
  874.         //
  875.         // File must be of the form xxx.java where xxx is a
  876.         // character string consisting of at least one character.
  877.         //
  878.         if (file_name_length < FileSymbol::java_suffix_length ||
  879.             (! FileSymbol::IsJavaSuffix(&file_name[file_name_length - FileSymbol::java_suffix_length])))
  880.             bad_input_filenames.Next() = name;
  881.         else
  882.         {
  883.             FileSymbol *file_symbol = FindOrInsertJavaInputFile(name, file_name_length - FileSymbol::java_suffix_length);
  884.  
  885.             if (! file_symbol)
  886.                 unreadable_input_filenames.Next() = name;
  887.             else
  888.             {
  889.                 delete [] name;
  890.                 file_set.AddElement(file_symbol);
  891.             }
  892.         }
  893.     }
  894.  
  895.     return;
  896. }
  897.  
  898.  
  899. FileSymbol *Control::FindOrInsertJavaInputFile(DirectorySymbol *directory_symbol, NameSymbol *file_name_symbol)
  900. {
  901.     FileSymbol *file_symbol = NULL;
  902.  
  903.     int length = file_name_symbol -> Utf8NameLength() + FileSymbol::java_suffix_length;
  904.     char *java_name = new char[length + 1]; // +1 for \0
  905.     strcpy(java_name, file_name_symbol -> Utf8Name());
  906.     strcat(java_name, FileSymbol::java_suffix);
  907.  
  908.     DirectoryEntry *entry = directory_symbol -> FindEntry(java_name, length);
  909.     if (entry)
  910.     {
  911.         file_symbol = directory_symbol -> FindFileSymbol(file_name_symbol);
  912.  
  913.         if (! file_symbol)
  914.         {
  915.             file_symbol = directory_symbol -> InsertFileSymbol(file_name_symbol);
  916.             file_symbol -> directory_symbol = directory_symbol;
  917.             file_symbol -> SetJava();
  918.         }
  919.  
  920.         file_symbol -> mtime = entry -> Mtime();
  921.     }
  922.  
  923.     delete [] java_name;
  924.  
  925.     return file_symbol;
  926. }
  927.  
  928.  
  929. FileSymbol *Control::FindOrInsertJavaInputFile(wchar_t *name, int name_length)
  930. {
  931.     FileSymbol *file_symbol = NULL;
  932.  
  933.     //
  934.     // The name has been preprocessed so that if it contains any
  935.     // slashes it is a forward slash. In the loop below we look
  936.     // for the occurrence of the first slash (if any) that separates
  937.     // the file name from its directory name.
  938.     //
  939.     DirectorySymbol *directory_symbol;
  940.     NameSymbol *file_name_symbol;
  941. #if defined(UNIX_FILE_SYSTEM) || defined(AMIGAOS_FILE_SYSTEM)
  942.     int len;
  943.     for (len = name_length - 1; len >= 0 && name[len] != U_SLASH; len--)
  944.         ;
  945.     directory_symbol = ProcessSubdirectories(name, len);
  946.     file_name_symbol = FindOrInsertName(&name[len + 1], name_length - (len + 1));
  947. #elif defined(WIN32_FILE_SYSTEM)
  948.     int len;
  949.     for (len = name_length - 1; len >= 0 && name[len] != U_SLASH && name[len] != U_COLON; len--)
  950.         ;
  951.     directory_symbol = ProcessSubdirectories(name, (name[len] == U_COLON ? len + 1 : len));
  952.     file_name_symbol = FindOrInsertName(&name[len + 1], name_length - (len + 1));
  953. #endif
  954.  
  955.     for (int i = 1; i < classpath.Length(); i++)
  956.     {
  957.         if (i == dot_classpath_index) // the current directory (.).
  958.         {
  959.             file_symbol = FindOrInsertJavaInputFile(directory_symbol, file_name_symbol);
  960.             if (file_symbol)
  961.                 break;
  962.         }
  963.         else if (classpath[i] -> IsZip())
  964.         {
  965.             DirectorySymbol *directory_symbol = FindSubdirectory(classpath[i], name, len);
  966.             if (directory_symbol)
  967.             {
  968.                 file_symbol = directory_symbol -> FindFileSymbol(file_name_symbol);
  969.                 if (file_symbol && file_symbol -> IsJava())
  970.                      break;
  971.                 else file_symbol = NULL;
  972.             }
  973.         }
  974.     }
  975.  
  976.     //
  977.     // If the file was found, return it; otherwise, in case the (.) directory was not specified in the
  978.     // classpath, search for the file in it...
  979.     //
  980.     return (file_symbol ? file_symbol : FindOrInsertJavaInputFile(directory_symbol, file_name_symbol));
  981. }
  982.  
  983.  
  984. PackageSymbol *Control::FindOrInsertPackage(LexStream *lex_stream, AstExpression *name)
  985. {
  986.     PackageSymbol *package;
  987.  
  988.     AstFieldAccess* field_access = name -> FieldAccessCast();
  989.     if (field_access)
  990.     {
  991.         package = FindOrInsertPackage(lex_stream, field_access -> base);
  992.         NameSymbol *name_symbol = lex_stream -> NameSymbol(field_access -> identifier_token);
  993.         PackageSymbol *subpackage = package -> FindPackageSymbol(name_symbol);
  994.         if (! subpackage)
  995.             subpackage = package -> InsertPackageSymbol(name_symbol);
  996.         package = subpackage;
  997.     }
  998.     else
  999.     {
  1000.         AstSimpleName *simple_name = (AstSimpleName *) name;
  1001.         NameSymbol *name_symbol = lex_stream -> NameSymbol(simple_name -> identifier_token);
  1002.         package = external_table.FindPackageSymbol(name_symbol);
  1003.         if (! package)
  1004.             package = external_table.InsertPackageSymbol(name_symbol, NULL);
  1005.     }
  1006.  
  1007.     FindPathsToDirectory(package);
  1008.  
  1009.     return package;
  1010. }
  1011.  
  1012.  
  1013. void Control::ProcessFile(FileSymbol *file_symbol)
  1014. {
  1015.     ProcessHeaders(file_symbol);
  1016.  
  1017.     //
  1018.     // As long as there are new bodies, ...
  1019.     //
  1020.     for (int i = 0; i < needs_body_work.Length(); i++)
  1021.     {
  1022.         assert(semantic.Length() == 0);
  1023.  
  1024.         ProcessBodies(needs_body_work[i]);
  1025.     }
  1026.     needs_body_work.Reset();
  1027.  
  1028.     return;
  1029. }
  1030.  
  1031.  
  1032. void Control::ProcessHeaders(FileSymbol *file_symbol)
  1033. {
  1034.     input_java_file_set.AddElement(file_symbol);
  1035.  
  1036.     bool initial_invocation = (semantic.Length() == 0);
  1037.  
  1038.     if (option.verbose)
  1039.     {
  1040.         Coutput << "[read "
  1041.                 << file_symbol -> FileName()
  1042.                 << "]\n";
  1043.     }
  1044.  
  1045.     if (! file_symbol -> lex_stream)
  1046.          scanner -> Scan(file_symbol);
  1047.     else file_symbol -> lex_stream -> Reset();
  1048.  
  1049.     if (file_symbol -> lex_stream) // do we have a successful scan!
  1050.     {
  1051.         if (! file_symbol -> compilation_unit)
  1052.             file_symbol -> compilation_unit = parser -> HeaderParse(file_symbol -> lex_stream);
  1053.         //
  1054.         // If we have a compilation unit, analyze it, process its types.
  1055.         //
  1056.         if (file_symbol -> compilation_unit)
  1057.         {
  1058.             assert(! file_symbol -> semantic);
  1059.  
  1060.             if (! file_symbol -> package)
  1061.                 ProcessPackageDeclaration(file_symbol, file_symbol -> compilation_unit -> package_declaration_opt);
  1062.             file_symbol -> semantic = new Semantic(*this, file_symbol);
  1063.             semantic.Next() = file_symbol -> semantic;
  1064.             file_symbol -> semantic -> ProcessTypeNames();
  1065.         }
  1066.     }
  1067.  
  1068.     if (initial_invocation)
  1069.         ProcessMembers();
  1070.  
  1071.     return;
  1072. }
  1073.  
  1074.  
  1075. void Control::ProcessMembers()
  1076. {
  1077.     Tuple<TypeSymbol *> partially_ordered_types(1024);
  1078.     SymbolSet needs_member_work(101);
  1079.     TypeCycleChecker cycle_checker(partially_ordered_types);
  1080.     TopologicalSort topological_sorter(needs_member_work, partially_ordered_types);
  1081.  
  1082.     int start = 0;
  1083.     while (start < semantic.Length())
  1084.     {
  1085.         needs_member_work.SetEmpty();
  1086.  
  1087.         do
  1088.         {
  1089.             //
  1090.             // Check whether or not there are cycles in this new batch of types.
  1091.             // Create a partial order of the types (cycles are ordered arbitrarily)
  1092.             // and place the result in partially_ordered_types.
  1093.             //
  1094.             cycle_checker.PartialOrder(semantic, start);
  1095.             start = semantic.Length(); // next starting point
  1096.  
  1097.             //
  1098.             // Process the extends and implements clauses.
  1099.             //
  1100.             for (int j = 0; j < partially_ordered_types.Length(); j++)
  1101.             {
  1102.                 TypeSymbol *type = partially_ordered_types[j];
  1103.                 needs_member_work.AddElement(type);
  1104.                 type -> ProcessTypeHeaders();
  1105.                 type -> semantic_environment -> sem -> types_to_be_processed.AddElement(type);
  1106.             }
  1107.         } while (start < semantic.Length());
  1108.  
  1109.         //
  1110.         // Patially order the collection of types in needs_member_work and place the result
  1111.         // in partially_ordered_types. This reordering is based on the complete "supertype"
  1112.         // information computed in ProcessTypeHeaders.
  1113.         //
  1114.         topological_sorter.Sort();
  1115.         for (int i = 0; i < partially_ordered_types.Length(); i++)
  1116.         {
  1117.             TypeSymbol *type = partially_ordered_types[i];
  1118.             needs_body_work.Next() = type;
  1119.             type -> ProcessMembers();
  1120.         }
  1121.     }
  1122.  
  1123.     semantic.Reset();
  1124.  
  1125.     return;
  1126. }
  1127.  
  1128.  
  1129.  
  1130. void Control::ProcessBodies(TypeSymbol *type)
  1131. {
  1132.     Semantic *sem = type -> semantic_environment -> sem;
  1133.  
  1134.     if (type -> declaration && (! sem -> compilation_unit -> BadCompilationUnitCast()))
  1135.     {
  1136.         AstInterfaceDeclaration *interface_declaration = type -> declaration -> InterfaceDeclarationCast();
  1137.         AstClassDeclaration *class_declaration = type -> declaration -> ClassDeclarationCast();
  1138.  
  1139. #ifdef WIN32_FILE_SYSTEM
  1140.         if (! type -> file_symbol -> IsZip())
  1141.         {
  1142.             int length = type -> Utf8NameLength() + FileSymbol::class_suffix_length;
  1143.             char *classfile_name = new char[length + 1]; // +1 for "\0"
  1144.             strcpy(classfile_name, type -> Utf8Name());
  1145.             strcat(classfile_name, FileSymbol::class_suffix);
  1146.  
  1147.             DirectorySymbol *directory = type -> file_symbol -> OutputDirectory();
  1148.             DirectoryEntry *entry = directory -> FindCaseInsensitiveEntry(classfile_name, length);
  1149.  
  1150.             //
  1151.             // If no entry exists for the classfile name, add it as we are about to create
  1152.             // such a file. If an entry is found and it is not identical (in a case-sensitive test)
  1153.             // to the name of the type, issue an appropriate message.
  1154.             //
  1155.             if (! entry)
  1156.                 directory -> InsertEntry(classfile_name, length);
  1157.             else if (strcmp(classfile_name, entry -> name) != 0)
  1158.             {
  1159.                 wchar_t *entry_name = new wchar_t[entry -> length + 1];
  1160.                 for (int i = 0; i < length; i++)
  1161.                     entry_name[i] = entry -> name[i];
  1162.                 entry_name[entry -> length] = U_NULL;
  1163.                 LexStream::TokenIndex identifier_token = (interface_declaration ? interface_declaration -> identifier_token
  1164.                                                                                 : class_declaration -> identifier_token);
  1165.  
  1166.                 sem -> ReportSemError(SemanticError::FILE_FILE_CONFLICT,
  1167.                                       identifier_token,
  1168.                                       identifier_token,
  1169.                                       type -> Name(),
  1170.                                       entry_name,
  1171.                                       directory -> Name());
  1172.  
  1173.                 delete [] entry_name;
  1174.             }
  1175.  
  1176.             delete [] classfile_name;
  1177.         }
  1178. #endif
  1179.  
  1180.         if (interface_declaration)
  1181.         {
  1182.             if (! parser -> InitializerParse(sem -> lex_stream, interface_declaration))
  1183.                 sem -> compilation_unit -> kind = Ast::BAD_COMPILATION; // recall that syntax errors were detected
  1184.             else
  1185.             {
  1186.                 type -> CompleteSymbolTable();
  1187.                 if (! parser -> BodyParse(sem -> lex_stream, interface_declaration))
  1188.                      sem -> compilation_unit -> kind = Ast::BAD_COMPILATION; // mark that syntax errors were detected
  1189.                 else type -> ProcessExecutableBodies();
  1190.             }
  1191.         }
  1192.         else
  1193.         {
  1194.             if (! parser -> InitializerParse(sem -> lex_stream, class_declaration -> class_body))
  1195.                 sem -> compilation_unit -> kind = Ast::BAD_COMPILATION; // recall that syntax errors were detected
  1196.             else
  1197.             {
  1198.                 type -> CompleteSymbolTable();
  1199.                 if (! parser -> BodyParse(sem -> lex_stream, class_declaration -> class_body))
  1200.                      sem -> compilation_unit -> kind = Ast::BAD_COMPILATION; // mark that syntax errors were detected.
  1201.                 else type -> ProcessExecutableBodies();
  1202.             }
  1203.         }
  1204.  
  1205.         if ((sem -> NumErrors() == 0) && (! sem -> compilation_unit -> BadCompilationUnitCast()))
  1206.         {
  1207.             Tuple<TypeSymbol *> *types = new Tuple<TypeSymbol *>(1024);
  1208.             types -> Next() = type;
  1209.  
  1210.             for (int j = 0; j < type -> num_anonymous_types(); j++)
  1211.             {
  1212.                 types -> Next() = type -> AnonymousType(j);
  1213.             }
  1214.  
  1215.             if (type -> local)
  1216.             {
  1217.                 for (TypeSymbol *local_type = (TypeSymbol *) type -> local -> FirstElement();
  1218.                                  local_type;
  1219.                                  local_type = (TypeSymbol *) type -> local -> NextElement())
  1220.                 {
  1221.                     types -> Next() = local_type;
  1222.                 }
  1223.             }
  1224.  
  1225.             if (type -> non_local)
  1226.             {
  1227.                 for (TypeSymbol *non_local_type = (TypeSymbol *) type -> non_local -> FirstElement();
  1228.                                  non_local_type;
  1229.                                  non_local_type = (TypeSymbol *) type -> non_local -> NextElement())
  1230.                 {
  1231.                     types -> Next() = non_local_type;
  1232.                 }
  1233.             }
  1234.  
  1235.             //
  1236.             // If we are supposed to generate code, do so now !!!
  1237.             //
  1238.             if (option.bytecode)
  1239.             {
  1240.                 for (int k = 0; k < types -> Length(); k++)
  1241.                 {
  1242.                     TypeSymbol *type = (*types)[k];
  1243.  
  1244.                     type -> file_symbol -> SetFileNameLiteral((Control *) this); // make sure the literal is available for bytecode
  1245.  
  1246.                     ByteCode *code = new ByteCode(type);
  1247.                     code -> GenerateCode();
  1248.  
  1249.                     delete code;
  1250.                 }
  1251.             }
  1252.  
  1253.             //
  1254.             // If no error was detected while generating code, then
  1255.             // start cleaning up.
  1256.             //
  1257.             if (sem -> NumErrors() == 0)
  1258.             {
  1259.                 for (int k = 0; k < types -> Length(); k++)
  1260.                 {
  1261.                     TypeSymbol *type = (*types)[k];
  1262.  
  1263.                     delete type -> semantic_environment;
  1264.                     type -> semantic_environment = NULL;
  1265.  
  1266.                     if (type -> ACC_INTERFACE())
  1267.                     {
  1268.                         AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) type -> declaration;
  1269.                         interface_declaration -> semantic_environment = NULL;
  1270.                     }
  1271.                     else
  1272.                     {
  1273.                         AstClassDeclaration *class_declaration = type -> declaration -> ClassDeclarationCast();
  1274.  
  1275.                         if (class_declaration)
  1276.                             class_declaration -> semantic_environment = NULL;
  1277.                     }
  1278.                 }
  1279.             }
  1280.  
  1281.             delete types;
  1282.         }
  1283.     }
  1284.  
  1285.     sem -> types_to_be_processed.RemoveElement(type);
  1286.     if (sem -> types_to_be_processed.Size() == 0) // all types belonging to this compilation unit have been processed.
  1287.         CleanUp(sem -> source_file_symbol);
  1288.  
  1289.     return;
  1290. }
  1291.  
  1292.  
  1293. //
  1294. // Introduce the main package and the current package.
  1295. // This procedure is invoked directly only while doing
  1296. // an incremental compilation.
  1297. //
  1298. void Control::ProcessPackageDeclaration(FileSymbol *file_symbol, AstPackageDeclaration *package_declaration)
  1299. {
  1300.     file_symbol -> package = (package_declaration
  1301.                                      ? FindOrInsertPackage(file_symbol -> lex_stream, package_declaration -> name)
  1302.                                      : unnamed_package);
  1303.  
  1304.     for (int i = 0; i < file_symbol -> lex_stream -> NumTypes(); i++)
  1305.     {
  1306.         LexStream::TokenIndex identifier_token = file_symbol -> lex_stream -> Next(file_symbol -> lex_stream -> Type(i));
  1307.         if (file_symbol -> lex_stream -> Kind(identifier_token) == TK_Identifier)
  1308.         {
  1309.             NameSymbol *name_symbol = file_symbol -> lex_stream -> NameSymbol(identifier_token);
  1310.             if (! file_symbol -> package -> FindTypeSymbol(name_symbol))
  1311.             {
  1312.                 TypeSymbol *type = file_symbol -> package -> InsertOuterTypeSymbol(name_symbol);
  1313.                 type -> file_symbol = file_symbol;
  1314.                 type -> outermost_type = type;
  1315.                 type -> SetOwner(file_symbol -> package);
  1316.                 type -> SetSignature(*this);
  1317.                 type -> MarkSourcePending();
  1318.  
  1319.                 //
  1320.                 // If this type is contained in the unnamed package add it to the set
  1321.                 // unnamed_package_types if a type of similar name was not already there.
  1322.                 //
  1323.                 if ((! package_declaration) && (unnamed_package_types.Image(type -> Identity()) == NULL))
  1324.                     unnamed_package_types.AddElement(type);
  1325.             }
  1326.         }
  1327.     }
  1328.  
  1329.     return;
  1330. }
  1331.  
  1332.  
  1333. void Control::CleanUp(FileSymbol *file_symbol)
  1334. {
  1335.     Semantic *sem = file_symbol -> semantic;
  1336.  
  1337.     if (sem)
  1338.     {
  1339. #ifdef TEST
  1340.         if (option.debug_dump_lex)
  1341.         {
  1342.             sem -> lex_stream -> Reset(); // rewind input and ...
  1343.             sem -> lex_stream -> Dump();  // dump it!
  1344.         }
  1345.         if (option.debug_dump_ast)
  1346.             sem -> compilation_unit -> Print(*sem -> lex_stream);
  1347. #endif
  1348.         sem -> PrintMessages();
  1349.         if (sem -> return_code > 0)
  1350.             return_code = 1;
  1351.  
  1352.         file_symbol -> CleanUp();
  1353.     }
  1354.  
  1355.     return;
  1356. }
  1357.